package service

import (
	"blizzard/app/dao"
	"blizzard/app/model"
	"blizzard/app/utils/code"
	"blizzard/app/utils/tool"
	"github.com/gogf/gf/errors/gerror"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/util/gconv"
)

var SignCard = new(serviceSignCard)

type serviceSignCard struct {}

func (s *serviceSignCard) Login(r *ghttp.Request, id int, m *model.CardLoginParam) (interface{}, error) {
	var (
		app *model.BxSoftware
		card *model.BxSingleCard
		err error
	)
	var times = 0
	err = dao.BxBlack.IsBlackMachine(m.CardNum)
	if err != nil {
		return nil, err
	}
	card, err = dao.BxSingleCard.IsSignCard(id, m.CardNum)
	if err != nil {
		return nil, err
	}
	if card.Congeal == 2 {
		return nil, gerror.New(code.CardStopError)
	}
	app, err = dao.BxSoftware.FindOne("id = ?", id)
	if err != nil {
		return nil, gerror.New(code.SoftwareErrorMsg)
	}
	if app.BindingType == 2 {
		if card.MachineCode != "" || card.MachineCode != m.MachineCode {
			return nil, gerror.New(code.SoftwareMachineError)
		}
	}
	if gconv.Int(card.Endtime) == 0 {
		times = tool.GetCardType(card.Time, card.TimeType)
	} else if app.SoftwareState != 3 {
		if gconv.Int(card.Endtime) <= tool.GetTime() {
			return nil, gerror.New(code.CardExpireMsg)
		}
	}
	if card.State == 2 {
		if gconv.Int(card.HeartBeat) >= tool.GetTime() {
			if app.LoginType == 2 && card.MachineCode != m.MachineCode && card.MachineCode != "" {
				return nil, gerror.New(code.CardOnlineMsg)
			}
		}
	}
	tk := tool.GetCardToken(m.AppKey, id)
	data := g.Map{}
	card.MachineCode = m.MachineCode
	card.Token = tk
	card.Logtime = tool.GetTimeString()
	card.Logip = r.GetClientIp()
	card.HeartBeat = gconv.String(tool.GetTime() + app.HeartTime)
	card.State = 2
	if times != 0 {
		card.Endtime = gconv.String(tool.GetTime() + times)
	}
	_, err = dao.BxSingleCard.Save(card)
	if err != nil {
		return nil, err
	}
	data["endtime"] = card.Endtime
	data["token"] = card.Token
	return data, nil
}

func (s *serviceSignCard) Logout(id int, m *model.CardLogoutParam) error {
	card, err := dao.BxSingleCard.IsSignCard(id, m.CardNum)
	if err != nil {
		return err
	}
	token := tool.ParseToken(m.Token, m.AppKey)
	err = token.Valid()
	if err != nil {
		return err
	}
	if gconv.Int(card.HeartBeat) < tool.GetTime() {
		return gerror.New(code.TokenExpireMsg)
	}
	data := g.Map{}
	data["state"] = 1
	data["token"] = ""
	data["heart_beat"] = tool.GetTime() - 10
	_, err = dao.BxSingleCard.Data(data).Where("cardnum = ? AND software_id = ?",
		m.CardNum,
		id).Update()
	if err != nil {
		return err
	}
	return nil
}

func (s *serviceSignCard) Heart(id int, m *model.CardHeartParam) error {
	card, err := dao.BxSingleCard.IsSignCard(id, m.CardNum)
	if err != nil {
		return err
	}
	token := tool.ParseToken(m.Token, m.AppKey)
	err = token.Valid()
	if err != nil {
		return err
	}
	if gconv.Int(card.HeartBeat) < tool.GetTime() {
		return gerror.New(code.TokenExpireMsg)
	}
	app, err := dao.BxSoftware.FindOne("id = ?", id)
	if err != nil {
		return err
	}
	if app.SoftwareState != 3 {
		if gconv.Int(card.Endtime) < tool.GetTime() {
			return gerror.New(code.CardExpireMsg)
		}
	}
	if card.State == 1 {
		return gerror.New(code.UserForced)
	}
	data := g.Map{}
	data["heart_beat"] = tool.GetTime() + app.HeartTime
	_, err = dao.BxSingleCard.Data(data).
		Where("cardnum = ? AND software_id = ?", m.CardNum, id).Update()
	if err != nil {
		return err
	}
	return nil
}

func (s *serviceSignCard) Unbind(id int, m *model.CardUnbindParam) (interface{}, error) {
	err := dao.BxBlack.IsBlackMachine(m.CardNum)
	if err != nil {
		return nil, err
	}
	card, err := dao.BxSingleCard.IsSignCard(id, m.CardNum)
	if err != nil {
		return nil, err
	}
	app, err := dao.BxSoftware.FindOne("id = ?", id)
	if err != nil {
		return nil, err
	}
	if app.BindingType != 2 {
		return nil, gerror.New(code.SoftwareMachine)
	}
	if card.MachineCode == m.MachineCode {
		return nil, gerror.New(code.SoftwareCodeError)
	}
	if app.BindingdelType == 2 {
		return nil, gerror.New(code.SoftwareCantUnbind)
	}
	if card.MachineCode == "" {
		return nil, gerror.New(code.SoftwareMachineNil)
	}
	data := g.Map{}
	res := g.Map{}
	if app.BindingdelTime > 0 {
		if gconv.Int(card.Endtime) - (app.BindingdelTime * 60) > tool.GetTime() {
			data["endtime"] = gconv.Int(card.Endtime) - (app.BindingdelTime * 60)
			res["unbind_time"] = app.BindingdelTime
		} else {
			return nil, gerror.New(code.UserTimeAdjective)
		}
	}
	data["machine_code"] = ""
	_, err = dao.BxSingleCard.Data(data).
		Where("cardnum = ? AND software_id = ?", m.CardNum, id).Update()
	if err != nil {
		return nil, err
	}
	return res, nil
}

func (s *serviceSignCard) GetCardData(id int, m *model.GetCardDataParam) (interface{}, error) {
	one, err := dao.BxSingleCard.IsSignCard(id, m.CardNum)
	if err != nil {
		return nil, err
	}
	data := g.Map{}
	data["card_data"] = one.CardData
	return data, nil
}

func (s *serviceSignCard) SetCardData(id int, m *model.SetCardDataParam) error {
	_, err := dao.BxSingleCard.IsSignCard(id, m.CardNum)
	if err != nil {
		return err
	}
	data := g.Map{}
	data["card_data"] = m.CardData
	_, err = dao.BxSingleCard.Data(data).
		Where("cardnum = ? AND software_id = ?", m.CardNum, id).Update()
	if err != nil {
		return err
	}
	return nil
}

func (s *serviceSignCard) GetInfo(id int, m *model.GetCardInfoParam) (interface{}, error) {
	card, err := dao.BxSingleCard.IsSignCard(id, m.CardNum)
	if err != nil {
		return nil, err
	}
	data := g.Map{}
	data["name"] = card.Name
	data["card_num"] = card.Cardnum
	data["time"] = card.Time
	data["time_type"] = card.TimeType
	data["create_time"] = card.CreateTime
	data["card_data"] = card.CardData
	return data, nil
}